#encoding=utf8
import numpy as np

def meanLength(ll):
    ll = [len(l) for l in ll ]
    return np.mean(ll)

def groupVectorSimilarity(a,b):
    #最简单的将向量组取均值，并且在计算余弦值
    a= a.mean(0);b= b.mean(0)
    return vectorCos(a, b)
def log_Matrix(CountMatrix):
    sp = CountMatrix.shape
    meanWords = np.sum(CountMatrix)/sp[0]
    CountMatrix = CountMatrix.astype(np.float64)
    CountMatrix+=meanWords*0.00001/sp[1] #为每个词汇加上一点点，背景噪声，避免log函数的0无穷
    divisor_V = np.sum(CountMatrix,axis=1) #只有列
    divisor_V = np.tile(divisor_V, (1,sp[1]) ).reshape(sp) #扩充成原矩阵大小
    probabilize_CountMatrix = CountMatrix/divisor_V
    log2pMatrix = np.log2(probabilize_CountMatrix)
    transpose = log2pMatrix.transpose(1,0)
    crossEntropy = -( probabilize_CountMatrix.dot(transpose) )
    return crossEntropy
def vectorCos(a,b,norm_a=None,norm_b=None):#cos(a,b) = a.b /(|a|*|b|)
    if norm_a is None: norm_a=np.linalg.norm(a)#用于加速
    if norm_b is None: norm_b=np.linalg.norm(b)#避免每次都计算度量值
    norm2mul = norm_a * norm_b
    return np.dot(a,b)/norm2mul
def MatrixCos(a,b=None,isTrimZeros=True):
    if b is None:b = np.array(a) #print('b is None')
    assert a.shape[1] == b.shape[1]
    if isTrimZeros:
        trimZeros = lambda a:a[:a.nonzero()[0][-1]+1]
        a=trimZeros(a);b=trimZeros(b)
    transpose = b.transpose(1,0)
    computeDot = a.dot(transpose)
    #这里可以加速
    norm2_a = np.apply_along_axis(lambda x:np.linalg.norm(x),1,a)
    norm2_b = np.apply_along_axis(lambda x:np.linalg.norm(x),1,b)
#     Z = np.ones((a.shape[0],b.shape[0]), np.float)
#     for i in range(Z.shape[0]):
#         for j in range(Z.shape[1]):
#             Z[i][j]=norm2_a[i]*norm2_b[j]
    #看老子加速
    Z = np.outer(norm2_a, norm2_b)
    MxCos = computeDot/Z
    return MxCos
def MatrixMeanCos(a,b,isTrimZeros=True):
    return MatrixCos(a, b,isTrimZeros).mean()
def MatrixMeanPower(a,b):
    transpose = b.transpose(1,0)
    computeDot = a.dot(transpose)
    return computeDot.mean()
def vectorOSdist(a,b):#欧氏距离
    return np.linalg.norm(a-b)
def MatrixOSMeanDist(a,b=None,isTrimZeros=True):
    if b is None:b = np.array(a)
    assert a.shape[1] == b.shape[1]
    if isTrimZeros:
        trimZeros = lambda a:a[:a.nonzero()[0][-1]+1]
        a=trimZeros(a);b=trimZeros(b)
    OSDs = np.zeros((a.shape[0],b.shape[0]))
    for i in range(a.shape[0]):
        for j in range(b.shape[0]):
            OSDs[i][j]=vectorOSdist(a[i], b[j])
    return OSDs.mean()

def superParameterSpace(start,end,varianceDownthresh,upPropotion,format_f=int):
    #超参数空间提供函数，内置参数空间优化方法：
    #一维网格搜索变化最大值不超过自身upPropotion，最小不小于varianceDownthresh
    oneDimentionaSpace = [start]
    while oneDimentionaSpace[-1]*upPropotion<varianceDownthresh:
        oneDimentionaSpace.append(oneDimentionaSpace[-1]+varianceDownthresh)
    while oneDimentionaSpace[-1]<end:
        oneDimentionaSpace.append(oneDimentionaSpace[-1]*(1+upPropotion))
    if oneDimentionaSpace[-1]>end: oneDimentionaSpace[-1]=end
    result = [format_f(param) for param in oneDimentionaSpace]
    return result
    
    
    
    
